<template>
  <div class="ws_tasks_module">
    <!-- vue-grid-item 组件通用工具栏 -->
    <header>
      <i class="iconfont icon-reset" />
    </header>
    <!-- 个性工具栏 -->
    <section class="tools">
      <el-select
        v-model="tasksDisplayMode"
        size="mini"
        popper-class="el-options"
        :popper-append-to-body="false"
      >
        <i
          slot="prefix"
          :class="['iconfont', tasksDisplayMode === 'panel' ? 'icon-view' : 'icon-table']"
        />
        <el-option label="看板模式" value="panel">
          <i class="iconfont icon-view" />
          <span>看板模式</span>
        </el-option>
        <el-option label="表格模式" value="table">
          <i class="iconfont icon-table" />
          <span>表格模式</span>
        </el-option>
      </el-select>
      <div v-if="tasksDisplayMode === 'table'" class="row-height button-mode">
        <select-button v-model="tableSize">
          <span slot="title"><i class="iconfont icon-row-height" />行高</span>
          <template slot="options">
            <el-option v-for="(v, k) in tasksTableSize" :key="k" :label="v" :value="k" />
          </template>
        </select-button>
      </div>
      <i class="iconfont icon-filter is-hover" @click="handleFilter" />
    </section>
    <section class="progress-panel">
      <!-- 看板模式 -->
      <template v-if="tasksDisplayMode === 'panel'">
        <div v-for="column in mock_tasks" :key="column.title" class="column">
          <div class="column-header">
            <span>{{ column.title }}</span>
            <span>{{ column.tasks.length }}</span>
            <span>
              <i class="iconfont icon-details"></i>
            </span>
          </div>
          <task-column class="column-body" :TaskColumnSettings="column.tasks" />
        </div>
      </template>
      <!-- 表格模式 -->
      <template v-else>
        <div class="table-list">
          <div v-for="(table, index) in mock_tasks" :key="table.title" class="table" ref="table">
            <div class="title">
              <span>{{ table.title }}</span>
              <span>{{ table.tasks.length }}</span>
              <i class="iconfont icon-details"></i>
            </div>
            <WsTableDraggable :wrapperKey="index" :animation="150" @onMove="onSortableMove">
              <el-table
                :data="table.tasks"
                size="mini"
                border
                style="width: 100%"
                :row-style="computeTableRowStyle"
              >
                <el-table-column
                  v-for="(v, key) in table.tasks[0]"
                  :key="key"
                  :prop="key"
                  :label="tasksColumnsZhCn[key]"
                >
                  <template v-if="key === 'status'" v-slot="scope">
                    <span class="task-tag" :style="computeTagClassName(scope.row.status)">
                      {{ scope.row.status }}
                    </span>
                  </template>
                </el-table-column>
              </el-table>
            </WsTableDraggable>
          </div>
        </div>
      </template>
    </section>
    <!-- filter 组件 -->
    <div v-if="isFiltering" ref="filter" class="filter-panel" v-clickoutside="handleClose">
      <header>
        <span>筛选</span>
        <span @click="clearFilterOptions">
          <i class="iconfont icon-ashbin" />
          <span>清除所有</span>
        </span>
      </header>
      <section>
        <div class="title">
          <span>工序类别</span>
        </div>
        <div class="body">
          <el-select
            v-model="filterOptions.procedureType"
            multiple
            size="medium"
            :popper-append-to-body="false"
          >
            <el-option
              v-for="option in ProcedureTypeList"
              :key="option"
              :label="option"
              :value="option"
            />
          </el-select>
        </div>
      </section>
      <section>
        <div class="title">
          <span>工序状态</span>
        </div>
        <div class="body">
          <el-checkbox
            :indeterminate="isIndeterminate"
            v-model="checkAll"
            @change="handleCheckAllChange"
          >
            全选
          </el-checkbox>
          <el-checkbox-group v-model="filterOptions.status" @change="handleCheckedStatusChange">
            <el-checkbox v-for="status in ProcedureStatus" :label="status" :key="status">
              {{ status }}
            </el-checkbox>
          </el-checkbox-group>
        </div>
      </section>
    </div>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
import { Component, Ref, Watch } from 'vue-property-decorator'
import { TaskCardType } from '@/interface/Basic'
import TaskColumn from '../General/TaskColumn.vue'
import { Dictionary } from 'vue-router/types/router'
import { ProcedureStatus } from '@/confirgurations/Basic'
import { default_wrapper_dark_color, default_wrapper_light_color } from '@/confirgurations/Basic'
import { Getter } from 'vuex-class'
import SelectButton from '@/components/tool/ws-select-button.vue'
import Sortable from 'sortablejs'
import WsTableDraggable from '@/components/tool/ws-table-draggble.vue'
@Component({
  components: {
    TaskColumn,
    SelectButton,
    WsTableDraggable
  }
})
class WSTasks extends Vue {
  @Getter('theme') theme!: 'dark' | 'light'
  @Ref() filter!: HTMLElement
  @Ref() table!: HTMLElement | HTMLElement[]
  /**
   * 通用的配置数据
   */
  ProcedureStatus = ProcedureStatus
  default_wrapper_dark_color = default_wrapper_dark_color
  default_wrapper_light_color = default_wrapper_light_color
  /**
   * 模拟的任务列表数据
   */
  mock_tasks: {
    title: string
    tasks: TaskCardType[]
  }[] = [
    {
      title: '进行中',
      tasks: [
        {
          name: 'CL-S初装',
          operator: '陈川',
          status: '已完成',
          savetime: '2023/3/28 9:21:33'
        },
        {
          name: '工况零流量',
          operator: '陈川',
          status: '异常继续',
          savetime: '2023/3/28 9:21:33'
        },
        {
          name: 'CL-S初装',
          operator: '陈川',
          status: '已完成',
          savetime: '2023/3/28 9:21:33'
        },
        {
          name: 'CL-S初装',
          operator: '陈川',
          status: '已完成',
          savetime: '2023/3/28 9:21:33'
        },
        {
          name: 'CL-S初装',
          operator: '陈川',
          status: '未完成',
          savetime: '2023/3/28 9:21:33'
        }
      ]
    },
    {
      title: '即将超时',
      tasks: [
        {
          name: 'CL-S初装',
          operator: '陈川',
          status: '已完成',
          savetime: '2023/3/28 9:21:33'
        },
        {
          name: 'CL-S初装',
          operator: '陈川',
          status: '已完成',
          savetime: '2023/3/28 9:21:33'
        },
        {
          name: 'CL-S初装',
          operator: '陈川',
          status: '已完成',
          savetime: '2023/3/28 9:21:33'
        },
        {
          name: 'CL-S初装',
          operator: '陈川',
          status: '已完成',
          savetime: '2023/3/28 9:21:33'
        },
        {
          name: 'CL-S初装',
          operator: '陈川',
          status: '已完成',
          savetime: '2023/3/28 9:21:33'
        }
      ]
    },
    {
      title: '已完成',
      tasks: [
        {
          name: 'CL-S初装',
          operator: '陈川',
          status: '已完成',
          savetime: '2023/3/28 9:21:33'
        },
        {
          name: 'CL-S初装',
          operator: '陈川',
          status: '已完成',
          savetime: '2023/3/28 9:21:33'
        },
        {
          name: 'CL-S初装',
          operator: '陈川',
          status: '已完成',
          savetime: '2023/3/28 9:21:33'
        },
        {
          name: 'CL-S初装',
          operator: '陈川',
          status: '已完成',
          savetime: '2023/3/28 9:21:33'
        },
        {
          name: 'CL-S初装',
          operator: '陈川',
          status: '已完成',
          savetime: '2023/3/28 9:21:33'
        }
      ]
    },
    {
      title: '已超时',
      tasks: [
        {
          name: 'CL-S初装',
          operator: '陈川',
          status: '已完成',
          savetime: '2023/3/28 9:21:33'
        },
        {
          name: 'CL-S初装',
          operator: '陈川',
          status: '异常停止',
          savetime: '2023/3/28 9:21:33'
        },
        {
          name: 'CL-S初装',
          operator: '陈川',
          status: '已完成',
          savetime: '2023/3/28 9:21:33'
        },
        {
          name: 'CL-S初装',
          operator: '陈川',
          status: '已完成',
          savetime: '2023/3/28 9:21:33'
        },
        {
          name: 'CL-S初装',
          operator: '陈川',
          status: '已完成',
          savetime: '2023/3/28 9:21:33'
        }
      ]
    }
  ]
  /**
   * 任务列表展示模式
   */
  tasksDisplayMode: 'panel' | 'table' = 'panel'
  tasksColumnsZhCn: Dictionary<string> = {
    name: '工序名',
    operator: '操作员',
    status: '工序状态',
    savetime: '保存时间'
  }
  tableSize: string = 'mini'
  tasksTableSize: Dictionary<string> = {
    mini: '低',
    small: '中',
    medium: '高'
  }
  @Watch('tasksDisplayMode')
  mode_handler(newVal: 'panel' | 'table') {
    if (newVal === 'table') {
      this.$nextTick(() => {
        const tables = this.table
        if (Array.isArray(tables)) {
          tables.forEach((table, index) => {
            table.animate(
              [
                { transform: 'translateY(100px)', opacity: 0 },
                { transform: 'translateY(0)', opacity: 1 }
              ],
              { duration: 800, delay: index * Math.random() * 200, easing: 'ease', fill: 'both' }
            )
          })
        } else {
          tables.animate(
            [
              { transform: 'translateY(100px)', opacity: 0 },
              { transform: 'translateY(0)', opacity: 1 }
            ],
            { duration: 800, easing: 'ease', fill: 'both' }
          )
        }
      })
    }
  }
  computeTagClassName(status: string) {
    const textColor = this.theme === 'dark' ? '#FFFFFF' : '#555555'
    return {
      color: status === '未完成' ? textColor : '#FFFFFF',
      backgroundColor:
        this.theme === 'dark'
          ? this.default_wrapper_dark_color[status]
          : this.default_wrapper_light_color[status]
    }
  }
  computeTableRowStyle() {
    const rowHeight: Dictionary<number> = {
      mini: 30,
      small: 60,
      medium: 90
    }
    return { height: rowHeight[this.tableSize] + 'px' }
  }
  // sortable listeners
  onSortableMove() {
    interface ExpandMoveEvent extends Sortable.MoveEvent {
      path: HTMLElement[]
    }
    const evt: ExpandMoveEvent = arguments[0]
    const table = evt.path.find(ele => ele.className === 'table')
    const tableList = evt.path.find(ele => ele.className === 'table-list')
    if (!table || !tableList) return
    const index = Array.from(tableList.children).findIndex(child => child === table)
    const dragged_row = evt.dragged.closest('tr')
    const related_row = evt.related.closest('tr')
    if (dragged_row && related_row) {
      const childrenList = Array.from((related_row.parentNode as HTMLTableRowElement).children)
      const [drag_index, related_index] = [
        childrenList.indexOf(dragged_row),
        childrenList.indexOf(related_row)
      ]
      const { tasks } = this.mock_tasks[index]
      const temp = tasks[drag_index]
      tasks[drag_index] = tasks[related_index]
      tasks[related_index] = temp
    }
  }
  /*
   * 筛选栏目配置
   */
  // 是否开启筛选功能
  isFiltering: boolean = false
  handleFilter() {
    if (this.isFiltering) return
    this.isFiltering = true
    this.$nextTick(() => {
      this.filter.animate([{ width: 0 }, { width: '300px' }], {
        duration: 800,
        easing: 'ease',
        fill: 'both'
      })
    })
  }
  handleClose() {
    this.filter.animate([{ width: '300px' }, { width: 0, padding: '10px 0' }], {
      duration: 800,
      easing: 'ease',
      fill: 'both'
    }).onfinish = () => {
      this.isFiltering = false
    }
  }
  // 过滤选项集合
  filterOptions: Dictionary<unknown> = {
    procedureType: [],
    status: []
  }
  // 从模拟任务数据中计算出工序名称集合
  get ProcedureTypeList() {
    const result: string[] = []
    this.mock_tasks.forEach(item => {
      item.tasks.forEach(task => {
        result.push(task.name)
      })
    })
    return [...new Set(result)]
  }
  clearFilterOptions() {
    this.filterOptions = {
      procedureType: [],
      status: []
    }
  }
  // 工序状态列表
  checkAll: boolean = true
  isIndeterminate: boolean = true
  handleCheckAllChange(val: any) {
    this.filterOptions.status = val ? this.ProcedureStatus : []
    this.isIndeterminate = false
  }
  handleCheckedStatusChange(value: string[]) {
    const checkedCount = value.length
    this.checkAll = checkedCount === this.ProcedureStatus.length
    this.isIndeterminate = checkedCount > 0 && checkedCount < this.ProcedureStatus.length
  }
}
export default WSTasks
</script>

<style lang="less" scoped>
@import '~@/styles/animation.less';
@import '~@/styles/theme.less';
@import '~@/styles/layout.less';
.ws_tasks_module {
  position: relative;
  width: 100%;
  touch-action: none;
  #flex(column, flex-start, flex-start);
  header {
    width: 100%;
    height: 23px;
    margin-bottom: 5px;
    #flex(row, center, flex-end);
  }
  .tools {
    box-sizing: border-box;
    padding: 5px;
    width: 100%;
    margin-bottom: 20px;
    border: solid 1px;
    #flex(row, center, flex-start);
    #color(background-color, --module-bg-color);
    #color(border-color, --primary-border-color);
    i {
      box-sizing: border-box;
      padding: 2px;
      transition: all 0.2s ease;
      #color(color, --primary-text-color);
    }
    .is-hover:hover {
      color: #ffffff;
      #color(background-color, --primary-blue-color);
    }
    /deep/.el-select {
      width: 100px;
      .icon-view {
        #color(color, --primary-green-color);
      }
      .icon-table {
        #color(color, --primary-blue-color);
      }
      .el-input {
        #flex(row, center, center);
        .el-input__prefix {
          left: 0;
          i {
            margin-bottom: 1.5px;
          }
        }
        .el-input__inner {
          border: 0;
          border-radius: 0;
          padding-left: 20px;
          padding-right: 0;
          #color(background-color, --module-bg-color);
        }
      }
    }
    .button-mode {
      box-sizing: border-box;
      padding: 2px 5px;
      border-radius: 3px;
      cursor: pointer;
      transition: all 0.2s ease;
      span {
        font-size: 12px;
        #color(color, --primary-text-color);
        #flex(row, center, flex-start);
      }
      .el-select {
        display: none;
      }
    }
    .button-mode:hover {
      #color(background-color, --primary-hover-text-color);
    }
  }
  .progress-panel {
    position: relative;
    flex: 1;
    width: 100%;
    overflow: auto;
    #flex(row, flex-start, flex-start);
    .column {
      box-sizing: border-box;
      height: 100%;
      margin-right: 20px;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: flex-start;
      .column-header {
        width: 100%;
        margin-bottom: 10px;
        display: flex;
        align-items: center;
        justify-content: space-between;
        span {
          box-sizing: border-box;
          display: flex;
          align-items: center;
          font-size: 14px;
          transition: all 0.2s ease;
          cursor: pointer;
          #color(color, --primary-text-color);
          i {
            font-size: 20px;
          }
        }
      }
      .column-body {
        flex: 1;
      }
    }
    .column:last-child {
      margin-right: 0;
    }
    .table-list {
      width: 100%;
      .table {
        margin-bottom: 30px;
        .title {
          box-sizing: border-box;
          padding: 5px 10px;
          width: 100%;
          border: solid 1px;
          border-bottom: 0;
          #flex(row, center, space-between);
          #color(border-color, --primary-border-color);
          span {
            font-size: 14px;
            #color(color, --primary-text-color);
          }
        }
        /deep/.el-table {
          .task-tag {
            box-sizing: border-box;
            padding: 5px;
            border-radius: 3px;
          }
        }
      }
    }
  }
  .filter-panel {
    position: absolute;
    right: 0;
    top: 0;
    box-sizing: border-box;
    padding: 10px;
    width: 300px;
    height: 100%;
    border: solid 1px;
    transform-origin: right;
    overflow: hidden;
    #color(background-color, --module-bg-color);
    #color(border-color, --primary-border-color);
    #shadow-color(-2px, 0, 4px, 0, --primary-shadow-color);
    header {
      width: 280px;
      margin-bottom: 8px;
      border-bottom: solid 1px;
      #flex(row, center, space-between);
      #color(border-bottom-color, --primary-border-color);
      span {
        font-size: 18px;
        font-weight: 600;
        #color(color, --primary-text-color);
      }
      span:last-child {
        font-size: 14px;
        font-weight: 400;
        cursor: pointer;
        #color(color, --primary-red-color);
      }
    }
    section {
      box-sizing: border-box;
      margin-bottom: 10px;
      padding-bottom: 10px;
      border-bottom: solid 1px;
      // overflow: hidden;
      width: 280px;
      #flex(column, flex-start, flex-start);
      #color(border-bottom-color, --primary-border-color);
      .title {
        width: 100%;
        font-size: 14px;
        margin-bottom: 5px;
        #flex(row, flex-start, flex-start);
        span {
          font-weight: 16px;
          #color(color, --primary-text-color);
        }
      }
      .body {
        width: 100%;
        #flex(column, flex-start, flex-start);
        /deep/.el-select {
          width: 100% !important;
        }
        .el-checkbox-group {
          flex-wrap: wrap;
          #flex(row, flex-start, flex-start);
          .el-checkbox {
            width: 80px;
            margin-right: 10px;
            #flex(row, center, space-between);
          }
          .el-checkbox:nth-child(3n) {
            margin-right: 0;
          }
        }
      }
    }
  }
}
/deep/.el-options {
  text-align: left;
  .el-select-dropdown__item {
    font-weight: 400;
    #color(color, --primary-text-color);
    #flex(row, center, flex-start);
  }
}
/deep/.drag-background-class {
  height: 100px;
  width: 100%;
  opacity: 1;
  background-color: #ffffff !important;
}
/deep/.drag-background-class:hover {
  background-color: #eef7ff !important;
}
.slide-left-enter-active,
.slide-left-leave-active {
  transform-origin: left;
  transition: all 0.5s ease;
}
.slide-left-enter,
.slide-left-leave-to {
  opacity: 0;
  transform: scaleX(0);
}
.slide-left-enter-to,
.slide-left-leave {
  opacity: 1;
  transform: scaleX(1);
}
</style>
